﻿#include "db_api_.h"

static int scantag()
{
	unsigned int i,j;
	int res = 0;
	unsigned int br;
	TAGRECORD rec;

	res += f_lseek(&hDB->fdb, 0);
	for(i=0,j=0; i<hDB->tag_count; i++)
	{
		int percent = i * 100 / hDB->tag_count;
		if (percent > 100)	percent = 100;
		hDB->cb(-555, percent);
		DB_SLP

		res += f_read(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
		if(is_archive(rec.path))
		{
			if(i != j)
			{
				long long tmp_offset = f_tell(&hDB->fdb);
				res += f_lseek(&hDB->fdb, sizeof(TAGRECORD) * j);
				res += f_write(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
				res += f_lseek(&hDB->fdb, tmp_offset);
			}
			j++;
		}
	}
	hDB->tag_count = j;
	return res;
}

int tag_build(void)
{
	int res = 0;

	assert(hDB->mount == 1);

	/* delete this by HarveyMao #661 */
	//hDB->tag_count = 0;

	res += f_open(&hDB->fdb, (const char*)(F_DBTAG), (unsigned char)(FA_READ | FA_WRITE));
	if (res) return -1;

	res += scantag();

	hDB->dirty &= ~MODULE_TAG;
	res += f_close(&hDB->fdb);
	hDB->cb(-666, 100);

	return 0;
}

int get_tag_record(char* path, TAGRECORD* record)
{
	unsigned int i;
	int res = 0;
	int done = 0;
	unsigned int br;

	res += f_open(&hDB->fdb, (const char*)(F_DBTAG), (unsigned char)(FA_READ | FA_WRITE));
	if (res) 
	{
		return -1;
	}

	for(i=0; i<hDB->tag_count; i++)
	{
		res += f_read(&hDB->fdb, record, sizeof(TAGRECORD), &br);
		if(FR_OK == res && br == sizeof(TAGRECORD))
		{
			if(dircmp(record->path, path)==0)
			{
				done = 1;
				break;
			}
		}
	}

	res += f_close(&hDB->fdb);
	if (done == 0)
	{
		memset(record, 0, sizeof(TAGRECORD));
	}
	return res ? -1 : done;
}

int add_tag(char* path, unsigned int No, unsigned int tag)
{
	unsigned int i;
	int res = 0;
	unsigned int br;
	int done = 0;
	TAGRECORD rec = {0};

	res += f_open(&hDB->fdb, (const char*)(F_DBTAG), (unsigned char)(FA_READ | FA_WRITE));
	if (res) return -1;

	for(i=0; i<hDB->tag_count; i++)
	{
		res += f_read(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
		if(FR_OK == res && br == sizeof(TAGRECORD))
		{
			if(dircmp(rec.path, path)==0)
			{
				rec.tag[No] = tag;
				res += f_lseek(&hDB->fdb, f_tell(&hDB->fdb) - sizeof(TAGRECORD));
				res += f_write(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
				done = 1;
				break;
			}
		}
	}

	if(!done)
	{
		memset(&rec, 0, sizeof(TAGRECORD));
		strcpy(rec.path, path);
		rec.tag[No] = tag;
		res += f_lseek(&hDB->fdb, sizeof(TAGRECORD) * hDB->tag_count);
		res += f_write(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
		hDB->tag_count++;
	}

	res += f_close(&hDB->fdb);

	if (tag == 0)
	{
		int delete_flag = 1;
		for (i = 0; i < MAXTAG; i++)
		{
			if (rec.tag[i])
			{
				delete_flag = 0;
				break;
			}
		}
		if (delete_flag)
		{
			res += delete_tag(path);
		}
	}
	return res;
}

int delete_tag(char* path)
{
	unsigned int i;
	int res = 0;
	unsigned int br;
	TAGRECORD rec = { 0 };

	res += f_open(&hDB->fdb, (const char*)(F_DBTAG), (unsigned char)(FA_READ | FA_WRITE));
	if (res) return -1;

	for (i = 0; i < hDB->tag_count; i++)
	{
		res += f_read(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
		if (FR_OK == res && br == sizeof(TAGRECORD))
		{
			if (dircmp(path, rec.path) == 0)
			{
				for (++i; i < hDB->tag_count; i++)
				{
					DB_SLP
					res += f_read(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
					if (res || sizeof(TAGRECORD) != br)	break;
					res += f_lseek(&hDB->fdb, f_tell(&hDB->fdb) - sizeof(TAGRECORD) * 2);
					res += f_write(&hDB->fdb, &rec, sizeof(TAGRECORD), &br);
					res += f_lseek(&hDB->fdb, f_tell(&hDB->fdb) + sizeof(TAGRECORD));

				}
				hDB->tag_count--;
			}
		}
	}
	res += f_close(&hDB->fdb);
	return res;
}
